use std::collections::{HashMap, HashSet, VecDeque};

#[derive(Clone)]
pub struct GroupMsg {
    all_queue: HashMap<i64, VecDeque<String>>,
    set_group: HashMap<String, HashSet<i64>>,
    status: GroupMsgStatus,
}

#[derive(Clone)]
struct GroupMsgStatus {
    queues: i64,
    sender: i64,
    msgs: i64,
    groups: i64,
}

impl GroupMsgStatus {
    pub fn new() -> GroupMsgStatus {
        GroupMsgStatus {
            queues: 0,
            sender: 0,
            msgs: 0,
            groups: 0,
        }
    }

    pub fn add_quques(&mut self) {
        self.queues += 1;
    }

    pub fn add_sender(&mut self) {
        self.sender += 1;
    }

    pub fn add_msgs(&mut self) {
        self.msgs += 1;
    }

    pub fn add_groups(&mut self) {
        self.groups += 1;
    }
}

impl GroupMsg {
    pub fn new() -> GroupMsg {
        GroupMsg {
            all_queue: HashMap::new(),
            set_group: HashMap::new(),
            status: GroupMsgStatus::new(),
        }
    }
    //init
    pub fn init(&mut self, id_list: Vec<i64>) {
        for id in id_list {
            self.all_queue.insert(id, VecDeque::new());
            self.status.add_quques();
        }
    }
    //status
    pub fn status(&self) -> HashMap<String, i64> {
        let mut stat = HashMap::new();
        stat.insert(String::from("queues"), self.status.queues);
        stat.insert(String::from("groups"), self.status.groups);
        stat.insert(String::from("msgs"), self.status.msgs);
        stat.insert(String::from("sender"), self.status.sender);

        stat
    }
    //debug
    pub fn debug(&self) -> HashMap<String, String> {
        let mut debug_map = HashMap::new();
        debug_map.insert(String::from("all_queue"), format!("{:?}", self.all_queue));
        debug_map.insert(String::from("set_group"), format!("{:?}", self.set_group));

        debug_map
    }
    //del_queue
    pub fn del_queue(&mut self, id: &i64) {
        if self.all_queue.contains_key(id) {
            self.all_queue.remove(id).expect("id is null");
        }
    }
    //add_queue
    pub fn add_queue(&mut self, id: i64) {
        self.all_queue.insert(id, VecDeque::new());
        self.status.add_quques();
    }
    //send_all_queue
    pub fn send_all_queue(&mut self, msg: String) {
        for queue in self.all_queue.values_mut() {
            queue.push_back(msg.clone());
            self.status.add_msgs();
        }
    }

    //pull
    pub fn pull(&mut self, id: &i64) -> String {
        let mut res = String::from("null");
        match self.all_queue.get_mut(id) {
            Some(queue) => match queue.pop_front() {
                Some(msg) => {
                    res = msg;
                    self.status.add_sender();
                }
                None => res = String::from("null"),
            },
            None => res = String::from("null"),
        }
        res
    }
    //push
    pub fn push(&mut self, id: &i64, msg: String) {
        match self.all_queue.get_mut(id) {
            Some(queue) => {
                queue.push_back(msg);
                self.status.add_msgs();
            }
            None => println!("id is None:{}", id),
        }
    }
    //new_group
    pub fn new_group(&mut self, group: String) {
        self.set_group.insert(group, HashSet::new());
        self.status.add_groups();
    }

    //remove_group
    pub fn remove_group(&mut self, group: &String) {
        if self.set_group.contains_key(group) {
            self.set_group.remove(group).expect("remove error");
        }
    }

    //send_group_message
    pub fn send_group_message(&mut self, group: &String, msg: String) {
        match self.set_group.get(group) {
            Some(group_set) => {
                for id in group_set {
                    match self.all_queue.get_mut(id) {
                        Some(queue) => {
                            queue.push_back(msg.clone());
                            self.status.add_msgs();
                        }
                        None => {}
                    }
                }
            }
            None => println!("{}", String::from("send_group_message  error")),
        }
    }

    //add_group_by_id
    pub fn add_group_by_id(&mut self, group: &String, id: &i64) {
        if self.all_queue.contains_key(id) {
            match self.set_group.get_mut(group) {
                Some(group_set) => {
                    group_set.insert(*id);
                }
                None => println!("{}", String::from("add_group_id  error")),
            }
        }
    }
    //del_group_by_id
    pub fn del_group_by_id(&mut self, group: &String, id: &i64) {
        if self.all_queue.contains_key(id) {
            match self.set_group.get_mut(group) {
                Some(group_set) => {
                    group_set.remove(id);
                }
                None => println!("{}", String::from("add_group_id  error")),
            }
        }
    }
}

// fn test() {
//     let mut queue = GroupMsg::new();
//     let id_list = vec![1, 2, 3, 4, 5];
//     queue.init(id_list);
//     let id: i64 = 1;
//     let id2: i64 = 6;
//     queue.del_queue(&id);
//     queue.add_queue(id2);
//     queue.push(&id2, String::from("s: Box<str>"));
//     queue.push(&id2, String::from("s: Box<str>"));
//     queue.send_all_queue(String::from("s: Box<str>"));
//     let straaa = queue.pull(&id2);
//     let group = String::from("chat1");
//     let group2 = String::from("chat2");
//     let group3 = String::from("chat3");
//     queue.new_group(group.clone());
//     queue.new_group(group2.clone());
//     queue.new_group(group3);
//     queue.remove_group(&group);
//     queue.add_group_by_id(&group2.clone(), &6);
//     queue.send_group_message(&group2, String::from("2333333333333"));
//     println!("pull:{}", straaa);
//     println!("status:{:?}", queue.status());
//     println!("debug:{:?}", queue.debug());
// }
